package com.jxpanda.infrastructure.core.tollkit;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;

@SuppressWarnings("unchecked")
public class GenericTypeKit {

    /**
     * 获取泛型的类型
     *
     * @param clazz       目标类
     * @param genericType 从中解析类型参数的泛型接口或超类，一般是目标类所继承的超类或者所实现的接口
     * @param index       下标
     * @return 泛型的类型
     */
    public static <T> Class<T> getSuperClassGenericType(final Class<?> clazz, final Class<?> genericType, int index) {
        Class<?>[] classes = GenericTypeKit.resolveTypeArguments(clazz, genericType);
        return classes == null ? null : (Class<T>) classes[index];
    }

    /**
     * 解析 clazz 继承（或实现）genericType 时所绑定的实际类型参数列表。
     *
     * @param clazz       要解析的类
     * @param genericType 带泛型的父类或接口，例如：BaseService.class、List.class
     * @return 类型参数对应的 Class 数组，找不到或无法解析时返回 null
     */
    public static Class<?>[] resolveTypeArguments(Class<?> clazz, Class<?> genericType) {
        // 1. 先在父类上找
        Type superType = clazz.getGenericSuperclass();
        Class<?>[] result = inspectParameterizedType(superType, genericType);
        if (result != null) {
            return result;
        }
        // 2. 再在接口上找
        for (Type itf : clazz.getGenericInterfaces()) {
            result = inspectParameterizedType(itf, genericType);
            if (result != null) {
                return result;
            }
        }
        // 3. 递归向上查找
        Class<?> parent = clazz.getSuperclass();
        if (parent != null && parent != Object.class) {
            return resolveTypeArguments(parent, genericType);
        }
        return null;
    }

    private static Class<?>[] inspectParameterizedType(Type type, Class<?> genericType) {
        if (!(type instanceof ParameterizedType parameterizedType)) {
            return null;
        }
        // 原始类型是否匹配
        if (!genericType.equals(parameterizedType.getRawType())) {
            return null;
        }
        Type[] actualTypes = parameterizedType.getActualTypeArguments();
        Class<?>[] classes = new Class<?>[actualTypes.length];
        for (int i = 0; i < actualTypes.length; i++) {
            classes[i] = extractClass(actualTypes[i]);
        }
        return classes;
    }

    private static Class<?> extractClass(Type type) {
        if (type instanceof Class<?> classType) {
            return classType;
        }
        if (type instanceof ParameterizedType parameterizedType) {
            // 嵌套的泛型，取最外层原始类型
            return (Class<?>) parameterizedType.getRawType();
        }
        if (type instanceof TypeVariable<?>) {
            // 类型变量（T、E……），此处无法直接获得，按需决定是抛异常还是返回 Object.class
            return Object.class;
        }
        throw new IllegalArgumentException("无法处理的 Type: " + type);
    }

}
